/**
 * @author Xiao Xin 
 * @description 
 * @version 1.0.0
 * @date 20210311
 * @copyright MIN-Group:国家重大科技基础设施-未来网络北大实验室：深圳市信息论与未来网络重点实验室
 */
var SelfEncodingBase = require('../encoding/SelfEncodingBase').SelfEncodingBase
var Encoder = require('../encoding/Encoder').Encoder
var Block = require('../encoding/Block').Block
var TLV = require('../encoding/TLV')
var {InitialAble,TlvComponentBase} = require('./TlvComponentBase')
var aggregation = require('../common/aggregation')//实现了多继承

const NackReasonUnknown = 0
const NackReasonDuplicate = 1
const NackReasonNoRoute = 2

function getNackReasonString(reason){
    switch (reason) {
        case NackReasonUnknown:
            return "Unknown"
        case NackReasonDuplicate:
            return "Duplicate"
        case NackReasonNoRoute:
            return "NoRoute"
    }
    return "Unknown"
}
/**
 * @description Nack 头部组件，包含改组件的网络包可以认为具有Nack语义
 */
class NackHeader extends aggregation(TlvComponentBase,InitialAble,SelfEncodingBase){
  constructor(){
    super()
    this.nackReason = BigInt(-1)//声明一个数为bigint时，必须要给他赋值
  }

  getNackReason(){
    return this.nackReason
  }

  setNackReason(value){
    this.nackReason = BigInt(value)
    this.doInitial()
  }

  /**
   * @description 将 NackHeader 线速编码为一个TLV
   * @param {Encoder} Encoder
   * @return {Number}
   */
  wireEncode(encoder){
    let totalLength = 0
		try {
			//编码 TLV-VALUE
			let tmpLen = encoder.prependNonNegativeInteger(this.nackReason)
			totalLength += tmpLen

			//编码 TLV-LENGTH
			tmpLen = encoder.prependVarNumber(BigInt(totalLength))
			totalLength += tmpLen

			//编码 TLV-TYPE
			tmpLen = encoder.prependVarNumber(TLV.ComponentType.TlvNackHeader)
			totalLength += tmpLen

			return totalLength
		} catch (error) {
			throw error
		}
  }

  /**
   * @description 从TLV Block中解码出一个NackHeader
   * @param {Block} block
   */
  wireDecode(block){
    try {
			//检查Type是否正确
			TLV.expectType(block.getType(),TLV.ComponentType.TlvNackHeader)
			let value = BigInt(TLV.readNonNegativeInteger(block.getValue(),0,block.getLength()))
            this.setNackReason(value)
		} catch (error) {
			throw error
		}
  }
}

module.exports = {
  NackHeader: NackHeader,
    getNackReasonString:getNackReasonString
}
